﻿# HanRSS Outlook Addin
import sys, _winreg
import urllib2, feedparser, login

from win32com import universal
from win32com.server.exception import COMException
from win32com.client import gencache, DispatchWithEvents, Dispatch
import win32api
import pythoncom
from win32com.client import constants
import win32ui
import win32con
import win32traceutil

toolbar_name = "Standard"

# Support for COM objects we use.
gencache.EnsureModule('{00062FFF-0000-0000-C000-000000000046}', 0, 9, 0, bForDemand=True)
gencache.EnsureModule('{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}', 0, 2, 1, bForDemand=True)
gencache.EnsureModule('{AC0714F2-3D04-11D1-AE7D-00A0C90F26F4}', 0, 1, 0, bForDemand=True)
universal.RegisterInterfaces('{AC0714F2-3D04-11D1-AE7D-00A0C90F26F4}', 0, 1, 0, ["_IDTExtensibility2"])

class ButtonEvent:
    def GetFeed(self, top_level_url, a_url, username, password):
        password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
        password_mgr.add_password(None, top_level_url, username, password)
        handler = urllib2.HTTPBasicAuthHandler(password_mgr)
        opener = urllib2.build_opener(handler)
        return opener.open(a_url)

    def OnClick(self, button, cancel):
        title = u"로그인".encode('mbcs')
        def_user = ''
        userid, password, empty = login.GetLogin(title, def_user)

        top_level_url = "http://www.hanrss.com/"

        if empty == 1:
            a_url = 'http://www.hanrss.com/api/get_starred_items.qst?empty=1'
        else:
            a_url = 'http://www.hanrss.com/api/get_starred_items.qst'

        if userid == password == None:            
            pass
        else:
            try:
                f = self.GetFeed(top_level_url, a_url, userid, password)
            except: 
                win32ui.MessageBox(u"중요한 글을 가져오는 데 실패하였습니다. 이메일과 비밀번호가 정확한지 확인부탁드립니다.".encode('mbcs'), u"한RSS".encode('mbcs'))
                return cancel

            try:            
                d = feedparser.parse(f)
            except:
                win32ui.MessageBox(u"중요한 글 데이타를 분석하는 데 실패하였습니다.".encode('mbcs'), u"한RSS".encode('mbcs'))
                return cancel

            items = FeedItems(d)
            fm = FolderManager()
            fm.AddItems(fm.root, items)
            win32ui.MessageBox(u"중요한 글 가져오기를 완료하였습니다.".encode('mbcs'), u"한RSS".encode('mbcs'))

        return cancel

class FolderManager:
    def __init__ (self):        
        self.ol = Dispatch("Outlook.Application")
        self.ns = self.ol.GetNamespace("MAPI")
        self.root = self.GetRootFolder(u"한RSS - 중요한 글")
        self.currentFolder = self.root

    def GetRootFolder(self, name):
        pFolder = self.ns.GetDefaultFolder(constants.olFolderInbox).Parent
        try:
            return pFolder.Folders[name]
        except pythoncom.com_error, (hr, msg, exc, arg):
            if hr == -2147352567:
                pFolder.Folders.Add(name)
                return self.GetRootFolder(name)

            print "The AddFolder call failed with code %d: %s" % (hr, msg)
            if exc is None:
                print "There is no extended error information"
            else:
                wcode, source, text, helpFile, helpId, scode = exc
                print text
                return None

    def AddItem(self, parent, child):
        item = parent.Items.Add(constants.olPostItem)
        item.Subject = child.title
        item.HTMLBody = '<div style="font-family:Verdana,Gulim;font-size:9pt;"><table width=100% border=0 cellpadding=0 cellspacing=0 style="font-family:Verdana,Gulim;font-size:9pt"><tr><td bgcolor=#DBD6D1><img width=1 height=1 alt=""></td></tr><tr><td bgcolor=#ebebd5 style="padding:5 2 6 2"><table width=100% border=0 cellpadding=0 cellspacing=0><tr><td style="font-size:10pt"><a href="' + child.link + '"><span style="font-weight:bold">' + child.title + '</span></a></td></tr></table></td></tr></table><table width=100% border=0 cellpadding=0 cellspacing=0 style="font-family:Verdana,Gulim;font-size:9pt"><tr><td style="padding:6 2 0 2;line-height:14pt;" class=description>' + child.summary + '</td></tr></table></div>'
        item.UnRead = True
        item.Save()

    def AddItems(self, parent, childs):
        for item in childs.items:
            self.AddItem(parent, item)

class FeedItem:
    def __init__ (self, rss_item):
        self.title   = rss_item['title']
        self.link    = rss_item['link']
        self.summary = rss_item['summary']
        self.updated = rss_item['updated']

class FeedItems:
    items = []
    def __init__ (self, rss_feed):
        for i in range(0, len(rss_feed.entries)):   
            self.items.insert(0, FeedItem(rss_feed.entries[i]))

class OutlookAddin:
    _com_interfaces_ = ['_IDTExtensibility2']
    _public_methods_ = []
    _reg_clsctx_ = pythoncom.CLSCTX_INPROC_SERVER
    _reg_clsid_ = "{9D0FCAE1-8470-4222-AACC-0563D411E528}"
    _reg_progid_ = "HanRSS.OutlookAddin"
    _reg_policy_spec_ = "win32com.server.policy.EventHandlerPolicy"

    def OnConnection(self, application, connectMode, addin, custom):
        print "OnConnection", application, connectMode, addin, custom
        activeExplorer = application.ActiveExplorer()
        if activeExplorer is not None:
            bars = activeExplorer.CommandBars
	    toolbar = bars.Item(toolbar_name)

            item = toolbar.Controls.Add(Type=constants.msoControlButton, Temporary=True)
            item = self.toolbarButton = DispatchWithEvents(item, ButtonEvent)
            item.Caption = u"중요한 글 가져오기"
            item.TooltipText = u"한RSS 서버에 저장된 중요한 글을 가져옵니다."
            item.BeginGroup = True
	    item.Enabled = True

            #item2 = toolbar.Controls.Add(Type=constants.msoControlPopup, Temporary=temporary)
            #item2.Caption = u"한RSS 아웃룩"
            #popupItem1 = item2.Control.Controls.Add(Type=constants.msoControlButton, Temporary=temporary)
            #popupItem1.Caption = u"설정"
            #popupItem2 = item2.Control.Controls.Add(Type=constants.msoControlButton, Temporary=temporary)
            #popupItem2.Caption = u"업데이트 확인"
            #popupItem3 = item2.Control.Controls.Add(Type=constants.msoControlButton, Temporary=temporary)
            #popupItem3.Caption = u"도움말"

        fm = FolderManager()

    def OnDisconnection(self, mode, custom):
        print "OnDisconnection"
    def OnAddInsUpdate(self, custom):
        print "OnAddInsUpdate", custom
    def OnStartupComplete(self, custom):
        print "OnStartupComplete", custom
    def OnBeginShutdown(self, custom):
        print "OnBeginShutdown", custom

def DllRegisterServer():
    klass = OutlookAddin
    key = _winreg.CreateKey(_winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Office\\Outlook\\Addins")
    subkey = _winreg.CreateKey(key, klass._reg_progid_)
    _winreg.SetValueEx(subkey, "CommandLineSafe", 0, _winreg.REG_DWORD, 0)
    _winreg.SetValueEx(subkey, "LoadBehavior", 0, _winreg.REG_DWORD, 3)
    _winreg.SetValueEx(subkey, "Description", 0, _winreg.REG_SZ, klass._reg_progid_)
    _winreg.SetValueEx(subkey, "FriendlyName", 0, _winreg.REG_SZ, klass._reg_progid_)

def DllUnregisterServer():
    klass = OutlookAddin
    try:
        _winreg.DeleteKey(_winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Office\\Outlook\\Addins\\" + klass._reg_progid_)
    except WindowsError:
        pass

if __name__ == '__main__':
    import win32com.server.register
    win32com.server.register.UseCommandLine(OutlookAddin)
    if "--unregister" in sys.argv:
        DllUnregisterServer()
    else:
        DllRegisterServer()
